package cn.tedu.imop.gateway.config;

import com.alibaba.cloud.sentinel.datasource.config.NacosDataSourceProperties;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Properties;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NacosWritableDataSource<T> implements WritableDataSource<T> {

    private NacosDataSourceProperties nacosDataSourceProperties;
    private ConfigService configService;
    private final Converter<T, String> configEncoder;
    private final Lock lock = new ReentrantLock(true);

    public NacosWritableDataSource(NacosDataSourceProperties nacosDataSourceProperties, Converter<T, String> configEncoder) {
        this.nacosDataSourceProperties = nacosDataSourceProperties;
        this.configEncoder = configEncoder;
        // 初始化 Nacos configService
        initConfigService();
    }

    private void initConfigService() {
        try {
            this.configService = NacosFactory.createConfigService(buildProperties(nacosDataSourceProperties));
        } catch (NacosException e) {
            throw new RuntimeException("Failed to initialize Nacos ConfigService", e);
        }
    }

    private Properties buildProperties(NacosDataSourceProperties nacosDataSourceProperties) {
        Properties properties = new Properties();
        if (StringUtils.isEmpty(nacosDataSourceProperties.getServerAddr())) {
            throw new IllegalArgumentException("Nacos server address cannot be empty");
        }
        properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosDataSourceProperties.getServerAddr());

        if (!StringUtils.isEmpty(nacosDataSourceProperties.getNamespace())) {
            properties.setProperty(PropertyKeyConst.NAMESPACE, nacosDataSourceProperties.getNamespace());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getUsername())) {
            properties.setProperty(PropertyKeyConst.USERNAME, nacosDataSourceProperties.getUsername());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getPassword())) {
            properties.setProperty(PropertyKeyConst.PASSWORD, nacosDataSourceProperties.getPassword());
        }
        System.out.println("properties:" + properties);
        return properties;
    }

    @Override
    public void write(T value) throws Exception {
        lock.lock();
        try {
            if (value == null || (value instanceof List && ((List<?>) value).isEmpty())) {
                System.err.println("Value is null or empty, nothing to write to Nacos.");
                return;
            }
            String valueStr = this.configEncoder.convert(value);
            System.out.println("Writing value to Nacos: " + valueStr);
            // 发布新配置
            configService.publishConfig(nacosDataSourceProperties.getDataId(), nacosDataSourceProperties.getGroupId(), valueStr, ConfigType.JSON.getType());
        } catch (Exception e) {
            System.err.println("Failed to write to Nacos: " + e.getMessage());
            throw new RuntimeException("Failed to write to Nacos", e);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void close() throws Exception {
        // No-op, or add any cleanup logic if needed
    }
}